// 版权所有2009年围棋作者。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

// 包ast声明用于表示Go语法树的类型
// 包装。
// None
package ast

import (
	"go/token"
	"strings"
)

// ----------------------------------------------------------------------------
// 接口
// None
// 节点主要有3类：表达式和类型节点，
// 语句节点和声明节点。节点名称通常为
// 匹配相应的Go spec产品名称，并将其与之匹配
// 相一致节点字段对应于各个零件
// 各自的产品。
// None
// 所有节点都包含位置信息，用于标记节点的开始
// 对应的源文本段；可通过
// Pos存取器方法。节点可能包含其他位置信息
// 对于可以在部件之间找到注释的语言构造
// 结构（通常为任何较大的、括号内的子部分）。
// 需要该位置信息来正确定位注释
// 打印构造时。

// 所有节点类型都实现节点接口。
type Node interface {
	Pos() token.Pos // 属于节点的第一个字符的位置
	End() token.Pos // 紧接节点后的第一个字符的位置
}

// 所有表达式节点都实现Expr接口。
type Expr interface {
	Node
	exprNode()
}

// 所有语句节点都实现Stmt接口。
type Stmt interface {
	Node
	stmtNode()
}

// 所有声明节点都实现Decl接口。
type Decl interface {
	Node
	declNode()
}

// ----------------------------------------------------------------------------
// 评论

// 注释节点表示单个节点
// None
// 文本字段包含不带回车符（\r）的注释文本
// 可能在来源中存在。因为注释的结束位置是
// 使用len（Text）计算，End（）报告的位置与
// 包含回车的注释的真实源结束位置。
type Comment struct {
	Slash token.Pos // 开始注释的“/”的位置
	Text  string    // 注释文本（不包括的“\n”
}

func (c *Comment) Pos() token.Pos { return c.Slash }
func (c *Comment) End() token.Pos { return token.Pos(int(c.Slash) + len(c.Text)) }

// CommentGroup表示一系列注释
// 没有其他代币，之间也没有空行。
// None
type CommentGroup struct {
	List []*Comment // len（列表）>0
}

func (g *CommentGroup) Pos() token.Pos { return g.List[0].Pos() }
func (g *CommentGroup) End() token.Pos { return g.List[len(g.List)-1].End() }

func isWhitespace(ch byte) bool { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' }

func stripTrailingWhitespace(s string) string {
	i := len(s)
	for i > 0 && isWhitespace(s[i-1]) {
		i--
	}
	return s[0:i]
}

// Text返回注释的文本。
// 注释标记(
// 删除前导和尾随空行。
// 注释指令，如“
// 将多个空行减少为一行，并修剪行上的尾随空间。
// 除非结果为空，否则它将换行终止。
func (g *CommentGroup) Text() string {
	if g == nil {
		return ""
	}
	comments := make([]string, len(g.List))
	for i, c := range g.List {
		comments[i] = c.Text
	}

	lines := make([]string, 0, 10) // 大多数评论少于10行
	for _, c := range comments {
		// 删除注释标记。
		// 解析器准确地给出了注释文本。
		switch c[1] {
		case '/':
			// -样式注释（末尾没有换行符）
			c = c[2:]
			if len(c) == 0 {
				// 空行
				break
			}
			if c[0] == ' ' {
				// 剥离第一个空间-示例测试所需
				c = c[1:]
				break
			}
			if isDirective(c) {
				// 忽视
				continue
			}
		case '*':
			/*-style comment */
			c = c[2 : len(c)-2]
		}

		// 在换行符上拆分。
		cl := strings.Split(c, "\n")

		// 走行，去掉尾随空白并添加到列表中。
		for _, l := range cl {
			lines = append(lines, stripTrailingWhitespace(l))
		}
	}

	// 删除前导空白行；转换运行
	// 将内部空行转换为单个空行。
	n := 0
	for _, line := range lines {
		if line != "" || n > 0 && lines[n-1] != "" {
			lines[n] = line
			n++
		}
	}
	lines = lines[0:n]

	// 添加最后一个“”条目以从联接获取尾随换行符。
	if n > 0 && lines[n-1] != "" {
		lines = append(lines, "")
	}

	return strings.Join(lines, "\n")
}

// isDirective报告c是否为注释指令。
func isDirective(c string) bool {
	// "
	// (修订)
	if strings.HasPrefix(c, "line ") {
		return true
	}

	// "
	// (修订)
	colon := strings.Index(c, ":")
	if colon <= 0 || colon+1 >= len(c) {
		return false
	}
	for i := 0; i <= colon+1; i++ {
		if i == colon {
			continue
		}
		b := c[i]
		if !('a' <= b && b <= 'z' || '0' <= b && b <= '9') {
			return false
		}
	}
	return true
}

// ----------------------------------------------------------------------------
// 表达式和类型

// 字段表示结构类型中的字段声明列表，
// 接口类型中的方法列表，或参数/结果声明
// 在签名中。
// 未命名参数（仅包含类型的参数列表）的Field.Names为nil
// 和嵌入式结构字段。在后一种情况下，字段名是类型名。
// 名称包含接口类型列表元素的单个名称“类型”。
// 属于相同类型列表的类型共享相同的“类型”标识符，该标识符也
// 记录该关键字的位置。
// None
type Field struct {
	Doc     *CommentGroup // 相关文件；还是零
	Names   []*Ident      // 字段/方法/（类型）参数名称，或类型“type”；还是零
	Type    Expr          // 字段/方法/参数类型，类型列表类型；还是零
	Tag     *BasicLit     // 字段标签；还是零
	Comment *CommentGroup // 行注释；还是零
}

func (f *Field) Pos() token.Pos {
	if len(f.Names) > 0 {
		return f.Names[0].Pos()
	}
	if f.Type != nil {
		return f.Type.Pos()
	}
	return token.NoPos
}

func (f *Field) End() token.Pos {
	if f.Tag != nil {
		return f.Tag.End()
	}
	if f.Type != nil {
		return f.Type.End()
	}
	if len(f.Names) > 0 {
		return f.Names[len(f.Names)-1].End()
	}
	return token.NoPos
}

// 字段列表表示由括号或大括号括起的字段列表。
type FieldList struct {
	Opening token.Pos // 左括号/大括号的位置（如有）
	List    []*Field  // 字段列表；还是零
	Closing token.Pos // 右括号/大括号的位置（如有）
}

func (f *FieldList) Pos() token.Pos {
	if f.Opening.IsValid() {
		return f.Opening
	}
	// 在这种情况下，列表不应为空；
	// 保持保守，防止不良的AST
	if len(f.List) > 0 {
		return f.List[0].Pos()
	}
	return token.NoPos
}

func (f *FieldList) End() token.Pos {
	if f.Closing.IsValid() {
		return f.Closing + 1
	}
	// 在这种情况下，列表不应为空；
	// 保持保守，防止不良的AST
	if n := len(f.List); n > 0 {
		return f.List[n-1].End()
	}
	return token.NoPos
}

// NumFields返回由FieldList表示的参数或结构字段数。
func (f *FieldList) NumFields() int {
	n := 0
	if f != nil {
		for _, g := range f.List {
			m := len(g.Names)
			if m == 0 {
				m = 1
			}
			n += m
		}
	}
	return n
}

// 表达式由由一个表达式组成的树表示
// 或以下多个具体表达式节点。
// None
type (
	// BadExpr节点是包含以下内容的表达式的占位符：
	// 无法为其创建正确表达式节点的语法错误
	// 创建。
	// None
	BadExpr struct {
		From, To token.Pos // 不良表达的位置范围
	}

	// Ident节点表示标识符。
	Ident struct {
		NamePos token.Pos // 标识符位置
		Name    string    // 标识符名称
		Obj     *Object   // 表示对象；还是零
	}

	// 一个省略号节点代表文件中的“…”类型
	// 参数列表或数组类型中的“…”长度。
	// None
	Ellipsis struct {
		Ellipsis token.Pos // “…”的位置
		Elt      Expr      // 省略号元素类型（仅限参数列表）；还是零
	}

	// BasicLit节点表示基本类型的文本。
	BasicLit struct {
		ValuePos token.Pos   // 文字位置
		Kind     token.Token // token.INT、token.FLOAT、token.IMAG、token.CHAR或token.STRING
		Value    string      // 文字字符串；e、 g.42、0x7f、3.14、1e-9、2.4i、'a'、'x7f'、'foo'或'\m\n\o`
	}

	// FuncLit节点表示函数文字。
	FuncLit struct {
		Type *FuncType  // 功能类型
		Body *BlockStmt // 功能体
	}

	// CompositeLit节点表示复合文字。
	CompositeLit struct {
		Type       Expr      // 文字类型；还是零
		Lbrace     token.Pos // “{”的位置
		Elts       []Expr    // 复合元素列表；还是零
		Rbrace     token.Pos // “}”的位置
		Incomplete bool      // 如果Elts列表中缺少（源）表达式，则为true
	}

	// ParenExpr节点表示带括号的表达式。
	ParenExpr struct {
		Lparen token.Pos // “（”的位置
		X      Expr      // 括号表达式
		Rparen token.Pos // “的立场”
	}

	// SelectorExpr节点表示后跟选择器的表达式。
	SelectorExpr struct {
		X   Expr   // 表示
		Sel *Ident // 字段选择器
	}

	// IndexExpr节点表示后跟索引的表达式。
	IndexExpr struct {
		X      Expr      // 表示
		Lbrack token.Pos // “[”的位置
		Index  Expr      // 索引表达式
		Rbrack token.Pos // “]”的位置
	}

	// SliceExpr节点表示后跟切片索引的表达式。
	SliceExpr struct {
		X      Expr      // 表示
		Lbrack token.Pos // “[”的位置
		Low    Expr      // 切片范围的开始；还是零
		High   Expr      // 切片范围结束；还是零
		Max    Expr      // 片的最大容量；还是零
		Slice3 bool      // 如果为3索引切片（存在2个冒号），则为true
		Rbrack token.Pos // “]”的位置
	}

	// TypeAssertExpr节点表示后跟
	// 类型断言。
	// None
	TypeAssertExpr struct {
		X      Expr      // 表示
		Lparen token.Pos // “（”的位置
		Type   Expr      // 断言类型；零表示X型开关（类型）
		Rparen token.Pos // “的立场”
	}

	// CallExpr节点表示后跟参数列表的表达式。
	CallExpr struct {
		Fun      Expr      // 函数表达式
		Lparen   token.Pos // “（”的位置
		Args     []Expr    // 函数参数；还是零
		Ellipsis token.Pos // “…”的位置（如果没有“…”，则为token.NoPos）
		Rparen   token.Pos // “的立场”
	}

	// StarExpr节点表示格式为“*”表达式的表达式。
	// 从语义上讲，它可以是一元“*”表达式，也可以是指针类型。
	// None
	StarExpr struct {
		Star token.Pos // “*”的位置
		X    Expr      // 操作数
	}

	// 一元表达式节点表示一元表达式。
	// 一元“*”表达式通过StarExpr节点表示。
	// None
	UnaryExpr struct {
		OpPos token.Pos   // Op的位置
		Op    token.Token // 操作人员
		X     Expr        // 操作数
	}

	// BinaryExpr节点表示二进制表达式。
	BinaryExpr struct {
		X     Expr        // 左操作数
		OpPos token.Pos   // Op的位置
		Op    token.Token // 操作人员
		Y     Expr        // 操作数
	}

	// KeyValueExpr节点表示（键：值）对
	// 在复合文本中。
	// None
	KeyValueExpr struct {
		Key   Expr
		Colon token.Pos // “的立场”
		Value Expr
	}
)

// 通道类型的方向由位指示
// 包含以下一个或两个常量的掩码。
// None
type ChanDir int

const (
	SEND ChanDir = 1 << iota
	RECV
)

// 一个类型由一个
// 一个或多个以下特定于类型的表达式
// 节点。
// None
type (
	// ArrayType节点表示数组或切片类型。
	ArrayType struct {
		Lbrack token.Pos // “[”的位置
		Len    Expr      // 省略号节点用于[…]T数组类型，nil用于切片类型
		Elt    Expr      // 元素类型
	}

	// StructType节点表示结构类型。
	StructType struct {
		Struct     token.Pos  // “struct”关键字的位置
		Fields     *FieldList // 字段声明列表
		Incomplete bool       // 如果字段列表中缺少（源）字段，则为true
	}

	// 指针类型通过StarExpr节点表示。

	// InterfaceType节点表示接口类型。
	InterfaceType struct {
		Interface  token.Pos  // “接口”关键字的位置
		Methods    *FieldList // 嵌入接口、方法或类型的列表
		Incomplete bool       // 如果方法列表中缺少（源）方法或类型，则为true
	}

	// MapType节点表示贴图类型。
	MapType struct {
		Map   token.Pos // “地图”关键字的位置
		Key   Expr
		Value Expr
	}

	// ChanType节点表示通道类型。
	ChanType struct {
		Begin token.Pos // “chan”关键字或“<-”的位置（以先到者为准）
		Arrow token.Pos // “<-”（如果没有“<-”，则为token.NoPos）
		Dir   ChanDir   // 通道方向
		Value Expr      // 值类型
	}
)

// 表达式/类型节点的Pos和End实现。

func (x *BadExpr) Pos() token.Pos  { return x.From }
func (x *Ident) Pos() token.Pos    { return x.NamePos }
func (x *Ellipsis) Pos() token.Pos { return x.Ellipsis }
func (x *BasicLit) Pos() token.Pos { return x.ValuePos }
func (x *FuncLit) Pos() token.Pos  { return x.Type.Pos() }
func (x *CompositeLit) Pos() token.Pos {
	if x.Type != nil {
		return x.Type.Pos()
	}
	return x.Lbrace
}
func (x *ParenExpr) Pos() token.Pos      { return x.Lparen }
func (x *SelectorExpr) Pos() token.Pos   { return x.X.Pos() }
func (x *IndexExpr) Pos() token.Pos      { return x.X.Pos() }
func (x *SliceExpr) Pos() token.Pos      { return x.X.Pos() }
func (x *TypeAssertExpr) Pos() token.Pos { return x.X.Pos() }
func (x *CallExpr) Pos() token.Pos       { return x.Fun.Pos() }
func (x *StarExpr) Pos() token.Pos       { return x.Star }
func (x *UnaryExpr) Pos() token.Pos      { return x.OpPos }
func (x *BinaryExpr) Pos() token.Pos     { return x.X.Pos() }
func (x *KeyValueExpr) Pos() token.Pos   { return x.Key.Pos() }
func (x *ArrayType) Pos() token.Pos      { return x.Lbrack }
func (x *StructType) Pos() token.Pos     { return x.Struct }
func (x *FuncType) Pos() token.Pos {
	if x.Func.IsValid() || x.Params == nil { // 见第3870期
		return x.Func
	}
	return x.Params.Pos() // 接口方法声明没有“func”关键字
}
func (x *InterfaceType) Pos() token.Pos { return x.Interface }
func (x *MapType) Pos() token.Pos       { return x.Map }
func (x *ChanType) Pos() token.Pos      { return x.Begin }

func (x *BadExpr) End() token.Pos { return x.To }
func (x *Ident) End() token.Pos   { return token.Pos(int(x.NamePos) + len(x.Name)) }
func (x *Ellipsis) End() token.Pos {
	if x.Elt != nil {
		return x.Elt.End()
	}
	return x.Ellipsis + 3 // len（“…”）
}
func (x *BasicLit) End() token.Pos       { return token.Pos(int(x.ValuePos) + len(x.Value)) }
func (x *FuncLit) End() token.Pos        { return x.Body.End() }
func (x *CompositeLit) End() token.Pos   { return x.Rbrace + 1 }
func (x *ParenExpr) End() token.Pos      { return x.Rparen + 1 }
func (x *SelectorExpr) End() token.Pos   { return x.Sel.End() }
func (x *IndexExpr) End() token.Pos      { return x.Rbrack + 1 }
func (x *SliceExpr) End() token.Pos      { return x.Rbrack + 1 }
func (x *TypeAssertExpr) End() token.Pos { return x.Rparen + 1 }
func (x *CallExpr) End() token.Pos       { return x.Rparen + 1 }
func (x *StarExpr) End() token.Pos       { return x.X.End() }
func (x *UnaryExpr) End() token.Pos      { return x.X.End() }
func (x *BinaryExpr) End() token.Pos     { return x.Y.End() }
func (x *KeyValueExpr) End() token.Pos   { return x.Value.End() }
func (x *ArrayType) End() token.Pos      { return x.Elt.End() }
func (x *StructType) End() token.Pos     { return x.Fields.End() }
func (x *FuncType) End() token.Pos {
	if x.Results != nil {
		return x.Results.End()
	}
	return x.Params.End()
}
func (x *InterfaceType) End() token.Pos { return x.Methods.End() }
func (x *MapType) End() token.Pos       { return x.Value.End() }
func (x *ChanType) End() token.Pos      { return x.Value.End() }

// exprNode（）确保只能创建表达式/类型节点
// 分配给一个Expr。
// None
func (*BadExpr) exprNode()        {}
func (*Ident) exprNode()          {}
func (*Ellipsis) exprNode()       {}
func (*BasicLit) exprNode()       {}
func (*FuncLit) exprNode()        {}
func (*CompositeLit) exprNode()   {}
func (*ParenExpr) exprNode()      {}
func (*SelectorExpr) exprNode()   {}
func (*IndexExpr) exprNode()      {}
func (*SliceExpr) exprNode()      {}
func (*TypeAssertExpr) exprNode() {}
func (*CallExpr) exprNode()       {}
func (*StarExpr) exprNode()       {}
func (*UnaryExpr) exprNode()      {}
func (*BinaryExpr) exprNode()     {}
func (*KeyValueExpr) exprNode()   {}

func (*ArrayType) exprNode()     {}
func (*StructType) exprNode()    {}
func (*FuncType) exprNode()      {}
func (*InterfaceType) exprNode() {}
func (*MapType) exprNode()       {}
func (*ChanType) exprNode()      {}

// ----------------------------------------------------------------------------
// 标识的方便功能

// NewIdent创建一个没有位置的新Ident。
// 对于由Go解析器以外的代码生成的AST非常有用。
// None
func NewIdent(name string) *Ident { return &Ident{token.NoPos, name, nil} }

// IsExported报告名称是否以大写字母开头。
// None
func IsExported(name string) bool { return token.IsExported(name) }

// IsExported报告id是否以大写字母开头。
// None
func (id *Ident) IsExported() bool { return token.IsExported(id.Name) }

func (id *Ident) String() string {
	if id != nil {
		return id.Name
	}
	return "<nil>"
}

// ----------------------------------------------------------------------------
// 声明

// 语句由一个由一个
// 或以下多个具体语句节点。
// None
type (
	// BADSMT节点是包含以下内容的语句的占位符：
	// 无法为其创建正确语句节点的语法错误
	// 创建。
	// None
	BadStmt struct {
		From, To token.Pos // 错误语句的位置范围
	}

	// DeclStmt节点表示语句列表中的声明。
	DeclStmt struct {
		Decl Decl // *带有常量、类型或变量标记的GenDecl
	}

	// EmptyStmt节点表示空语句。
	// 空语句的“位置”是位置
	// 紧跟其后的分号（显式或隐式）。
	// None
	EmptyStmt struct {
		Semicolon token.Pos // “下列事项的立场”
		Implicit  bool      // 如果设置了，则在源代码中省略“；”
	}

	// LabeledStmt节点表示带标签的语句。
	LabeledStmt struct {
		Label *Ident
		Colon token.Pos // “的立场”
		Stmt  Stmt
	}

	// ExprStmt节点表示（独立）表达式
	// 在声明列表中。
	// None
	ExprStmt struct {
		X Expr // 表示
	}

	// sendsmt节点表示send语句。
	SendStmt struct {
		Chan  Expr
		Arrow token.Pos // “<-”的位置
		Value Expr
	}

	// incdecsmt节点表示递增或递减语句。
	IncDecStmt struct {
		X      Expr
		TokPos token.Pos   // Tok位置
		Tok    token.Token // 公司或十二月
	}

	// AssignStmt节点表示一个赋值或
	// 一个简短的变量声明。
	// None
	AssignStmt struct {
		Lhs    []Expr
		TokPos token.Pos   // Tok位置
		Tok    token.Token // 分配令牌，定义
		Rhs    []Expr
	}

	// GoStmt节点表示go语句。
	GoStmt struct {
		Go   token.Pos // “go”关键字的位置
		Call *CallExpr
	}

	// DeferStmt节点表示defer语句。
	DeferStmt struct {
		Defer token.Pos // “延迟”关键字的位置
		Call  *CallExpr
	}

	// ReturnStmt节点表示return语句。
	ReturnStmt struct {
		Return  token.Pos // “return”关键字的位置
		Results []Expr    // 结果表达式；还是零
	}

	// BranchStmt节点表示中断、继续、转到、，
	// 或者错误的陈述。
	// None
	BranchStmt struct {
		TokPos token.Pos   // Tok位置
		Tok    token.Token // 关键字标记（中断、继续、转到、故障排除）
		Label  *Ident      // 标签名称；还是零
	}

	// BlockStmt节点表示大括号语句列表。
	BlockStmt struct {
		Lbrace token.Pos // “{”的位置
		List   []Stmt
		Rbrace token.Pos // “}”的位置，如果有（可能由于语法错误而不存在）
	}

	// IfStmt节点表示if语句。
	IfStmt struct {
		If   token.Pos // “如果”关键字的位置
		Init Stmt      // 初始化语句；还是零
		Cond Expr      // 条件
		Body *BlockStmt
		Else Stmt // else分支；还是零
	}

	// case子句表示表达式或类型开关语句的大小写。
	CaseClause struct {
		Case  token.Pos // “case”或“default”关键字的位置
		List  []Expr    // 表达式或类型列表；“无”表示默认情况
		Colon token.Pos // “的立场”
		Body  []Stmt    // 报表清单；还是零
	}

	// SwitchStmt节点表示表达式switch语句。
	SwitchStmt struct {
		Switch token.Pos  // “开关”关键字的位置
		Init   Stmt       // 初始化语句；还是零
		Tag    Expr       // 标签表达；还是零
		Body   *BlockStmt // 仅适用于案例条款
	}

	// TypeSwitchStmt节点表示类型开关语句。
	TypeSwitchStmt struct {
		Switch token.Pos  // “开关”关键字的位置
		Init   Stmt       // 初始化语句；还是零
		Assign Stmt       // x:=y（类型）或y（类型）
		Body   *BlockStmt // 仅适用于案例条款
	}

	// CommClause节点表示select语句的一种情况。
	CommClause struct {
		Case  token.Pos // “case”或“default”关键字的位置
		Comm  Stmt      // 发送或接收报表；“无”表示默认情况
		Colon token.Pos // “的立场”
		Body  []Stmt    // 报表清单；还是零
	}

	// SelectStmt节点表示select语句。
	SelectStmt struct {
		Select token.Pos  // “选择”关键字的位置
		Body   *BlockStmt // 仅逗号子句
	}

	// ForStmt表示for语句。
	ForStmt struct {
		For  token.Pos // “for”关键字的位置
		Init Stmt      // 初始化语句；还是零
		Cond Expr      // 条件还是零
		Post Stmt      // 迭代后语句；还是零
		Body *BlockStmt
	}

	// RangeSMT表示带有range子句的for语句。
	RangeStmt struct {
		For        token.Pos   // “for”关键字的位置
		Key, Value Expr        // 键，值可以为零
		TokPos     token.Pos   // Tok的位置；如果键==nil，则无效
		Tok        token.Token // 如果Key==nil、ASSIGN、DEFINE，则为非法
		X          Expr        // 值的范围超过
		Body       *BlockStmt
	}
)

// 语句节点的Pos和End实现。

func (s *BadStmt) Pos() token.Pos        { return s.From }
func (s *DeclStmt) Pos() token.Pos       { return s.Decl.Pos() }
func (s *EmptyStmt) Pos() token.Pos      { return s.Semicolon }
func (s *LabeledStmt) Pos() token.Pos    { return s.Label.Pos() }
func (s *ExprStmt) Pos() token.Pos       { return s.X.Pos() }
func (s *SendStmt) Pos() token.Pos       { return s.Chan.Pos() }
func (s *IncDecStmt) Pos() token.Pos     { return s.X.Pos() }
func (s *AssignStmt) Pos() token.Pos     { return s.Lhs[0].Pos() }
func (s *GoStmt) Pos() token.Pos         { return s.Go }
func (s *DeferStmt) Pos() token.Pos      { return s.Defer }
func (s *ReturnStmt) Pos() token.Pos     { return s.Return }
func (s *BranchStmt) Pos() token.Pos     { return s.TokPos }
func (s *BlockStmt) Pos() token.Pos      { return s.Lbrace }
func (s *IfStmt) Pos() token.Pos         { return s.If }
func (s *CaseClause) Pos() token.Pos     { return s.Case }
func (s *SwitchStmt) Pos() token.Pos     { return s.Switch }
func (s *TypeSwitchStmt) Pos() token.Pos { return s.Switch }
func (s *CommClause) Pos() token.Pos     { return s.Case }
func (s *SelectStmt) Pos() token.Pos     { return s.Select }
func (s *ForStmt) Pos() token.Pos        { return s.For }
func (s *RangeStmt) Pos() token.Pos      { return s.For }

func (s *BadStmt) End() token.Pos  { return s.To }
func (s *DeclStmt) End() token.Pos { return s.Decl.End() }
func (s *EmptyStmt) End() token.Pos {
	if s.Implicit {
		return s.Semicolon
	}
	return s.Semicolon + 1 /* len(";") */
}
func (s *LabeledStmt) End() token.Pos { return s.Stmt.End() }
func (s *ExprStmt) End() token.Pos    { return s.X.End() }
func (s *SendStmt) End() token.Pos    { return s.Value.End() }
func (s *IncDecStmt) End() token.Pos {
	return s.TokPos + 2 /* len("++") */
}
func (s *AssignStmt) End() token.Pos { return s.Rhs[len(s.Rhs)-1].End() }
func (s *GoStmt) End() token.Pos     { return s.Call.End() }
func (s *DeferStmt) End() token.Pos  { return s.Call.End() }
func (s *ReturnStmt) End() token.Pos {
	if n := len(s.Results); n > 0 {
		return s.Results[n-1].End()
	}
	return s.Return + 6 // len（“返回”）
}
func (s *BranchStmt) End() token.Pos {
	if s.Label != nil {
		return s.Label.End()
	}
	return token.Pos(int(s.TokPos) + len(s.Tok.String()))
}
func (s *BlockStmt) End() token.Pos {
	if s.Rbrace.IsValid() {
		return s.Rbrace + 1
	}
	if n := len(s.List); n > 0 {
		return s.List[n-1].End()
	}
	return s.Lbrace + 1
}
func (s *IfStmt) End() token.Pos {
	if s.Else != nil {
		return s.Else.End()
	}
	return s.Body.End()
}
func (s *CaseClause) End() token.Pos {
	if n := len(s.Body); n > 0 {
		return s.Body[n-1].End()
	}
	return s.Colon + 1
}
func (s *SwitchStmt) End() token.Pos     { return s.Body.End() }
func (s *TypeSwitchStmt) End() token.Pos { return s.Body.End() }
func (s *CommClause) End() token.Pos {
	if n := len(s.Body); n > 0 {
		return s.Body[n-1].End()
	}
	return s.Colon + 1
}
func (s *SelectStmt) End() token.Pos { return s.Body.End() }
func (s *ForStmt) End() token.Pos    { return s.Body.End() }
func (s *RangeStmt) End() token.Pos  { return s.Body.End() }

// stmtNode（）确保只能创建语句节点
// 分配给Stmt的。
// None
func (*BadStmt) stmtNode()        {}
func (*DeclStmt) stmtNode()       {}
func (*EmptyStmt) stmtNode()      {}
func (*LabeledStmt) stmtNode()    {}
func (*ExprStmt) stmtNode()       {}
func (*SendStmt) stmtNode()       {}
func (*IncDecStmt) stmtNode()     {}
func (*AssignStmt) stmtNode()     {}
func (*GoStmt) stmtNode()         {}
func (*DeferStmt) stmtNode()      {}
func (*ReturnStmt) stmtNode()     {}
func (*BranchStmt) stmtNode()     {}
func (*BlockStmt) stmtNode()      {}
func (*IfStmt) stmtNode()         {}
func (*CaseClause) stmtNode()     {}
func (*SwitchStmt) stmtNode()     {}
func (*TypeSwitchStmt) stmtNode() {}
func (*CommClause) stmtNode()     {}
func (*SelectStmt) stmtNode()     {}
func (*ForStmt) stmtNode()        {}
func (*RangeStmt) stmtNode()      {}

// ----------------------------------------------------------------------------
// 声明

// 等级库节点表示单个（不带括号）导入，
// 常量、类型或变量声明。
// None
type (
	// 等级库类型表示*ImportSpec、*ValueSpec和*TypeSpec中的任意一种。
	Spec interface {
		Node
		specNode()
	}

	// ImportSpec节点表示单个包导入。
	ImportSpec struct {
		Doc     *CommentGroup // 相关文件；还是零
		Name    *Ident        // 本地包名称（包括“.”）；还是零
		Path    *BasicLit     // 导入路径
		Comment *CommentGroup // 行注释；还是零
		EndPos  token.Pos     // 规格结束（如果非零，则覆盖路径位置）
	}

	// ValueSpec节点表示常量或变量声明
	// （ConstSpec或VarSpec生产）。
	// None
	ValueSpec struct {
		Doc     *CommentGroup // 相关文件；还是零
		Names   []*Ident      // 值名称（len（name）>0）
		Type    Expr          // 价值类型；还是零
		Values  []Expr        // 初始值；还是零
		Comment *CommentGroup // 行注释；还是零
	}
)

// 规范节点的Pos和End实现。

func (s *ImportSpec) Pos() token.Pos {
	if s.Name != nil {
		return s.Name.Pos()
	}
	return s.Path.Pos()
}
func (s *ValueSpec) Pos() token.Pos { return s.Names[0].Pos() }
func (s *TypeSpec) Pos() token.Pos  { return s.Name.Pos() }

func (s *ImportSpec) End() token.Pos {
	if s.EndPos != 0 {
		return s.EndPos
	}
	return s.Path.End()
}

func (s *ValueSpec) End() token.Pos {
	if n := len(s.Values); n > 0 {
		return s.Values[n-1].End()
	}
	if s.Type != nil {
		return s.Type.End()
	}
	return s.Names[len(s.Names)-1].End()
}
func (s *TypeSpec) End() token.Pos { return s.Type.End() }

// specNode（）确保只能创建spec节点
// 分配给某个规范。
// None
func (*ImportSpec) specNode() {}
func (*ValueSpec) specNode()  {}
func (*TypeSpec) specNode()   {}

// 声明由以下声明节点之一表示。
// None
type (
	// BadDecl节点是包含以下内容的声明的占位符：
	// 无法为其创建正确声明节点的语法错误
	// 创建。
	// None
	BadDecl struct {
		From, To token.Pos // 不良申报部位范围
	}

	// GenDecl节点（通用声明节点）表示导入，
	// 常量、类型或变量声明。有效的Lparen位置
	// （Lparen.IsValid（））表示带括号的声明。
	// None
	// Tok值与规格元件类型之间的关系：
	// None
	// token.IMPORT*ImportSpec
	// token.CONST*ValueSpec
	// token.TYPE*TypeSpec
	// token.VAR*ValueSpec
	// None
	GenDecl struct {
		Doc    *CommentGroup // 相关文件；还是零
		TokPos token.Pos     // Tok位置
		Tok    token.Token   // 导入、常量、类型或变量
		Lparen token.Pos     // “（”的位置，如有
		Specs  []Spec
		Rparen token.Pos // “'）”的位置（如有）
	}

	// FuncDecl节点表示函数声明。
	FuncDecl struct {
		Doc  *CommentGroup // 相关文件；还是零
		Recv *FieldList    // 接收器（方法）；或零（函数）
		Name *Ident        // 函数/方法名称
		Type *FuncType     // 函数签名：“func”关键字的类型和值参数、结果和位置
		Body *BlockStmt    // 功能体；或对于外部（非Go）功能为零
		// ToDo（RfFrdLee）考虑将TParams存储在这里，而不是函数类型
		// 它们仅对声明的函数有效
	}
)

// 声明节点的Pos和End实现。

func (d *BadDecl) Pos() token.Pos  { return d.From }
func (d *GenDecl) Pos() token.Pos  { return d.TokPos }
func (d *FuncDecl) Pos() token.Pos { return d.Type.Pos() }

func (d *BadDecl) End() token.Pos { return d.To }
func (d *GenDecl) End() token.Pos {
	if d.Rparen.IsValid() {
		return d.Rparen + 1
	}
	return d.Specs[0].End()
}
func (d *FuncDecl) End() token.Pos {
	if d.Body != nil {
		return d.Body.End()
	}
	return d.Type.End()
}

// declNode（）确保只能创建声明节点
// 分配给一个Decl的。
// None
func (*BadDecl) declNode()  {}
func (*GenDecl) declNode()  {}
func (*FuncDecl) declNode() {}

// ----------------------------------------------------------------------------
// 文件和包

// 文件节点表示Go源文件。
// None
// 注释列表按顺序包含源文件中的所有注释
// 外观，包括从其他节点指向的注释
// 通过文档和注释字段。
// None
// 用于正确打印包含注释的源代码（使用软件包
// go/format和go/printer），必须特别注意更新注释
// 当文件的语法树被修改时：为了打印，注释被散布
// 基于标记位置的标记之间。如果语法树节点是
// 移除或移动，也必须移除其附近的相关注释
// （从File.Comments列表中）或相应地移动（通过更新
// 职位）。注释图可用于促进其中一些操作。
// None
// 注释是否以及如何与节点关联取决于
// 操作程序对语法树的解释：Doc除外
// 和与节点直接关联的注释注释，其余注释
// 是“自由浮动”（另见第18593期和第20744期）。
// None
type File struct {
	Doc        *CommentGroup   // 相关文件；还是零
	Package    token.Pos       // “包”关键字的位置
	Name       *Ident          // 包名
	Decls      []Decl          // 顶层声明；还是零
	Scope      *Scope          // 包范围（仅此文件）
	Imports    []*ImportSpec   // 在此文件中导入
	Unresolved []*Ident        // 此文件中未解析的标识符
	Comments   []*CommentGroup // 源文件中所有注释的列表
}

func (f *File) Pos() token.Pos { return f.Package }
func (f *File) End() token.Pos {
	if n := len(f.Decls); n > 0 {
		return f.Decls[n-1].End()
	}
	return f.Name.End()
}

// 包节点表示一组源文件
// 共同构建一个Go包。
// None
type Package struct {
	Name    string             // 包名
	Scope   *Scope             // 跨所有文件的包范围
	Imports map[string]*Object // 包id映射->包对象
	Files   map[string]*File   // 按文件名转到源文件
}

func (p *Package) Pos() token.Pos { return token.NoPos }
func (p *Package) End() token.Pos { return token.NoPos }
